#include "lib/detect_recog.h"

CvMemStorage* storage = 0;
CvHaarClassifierCascade* cascade = 0;
CvHaarClassifierCascade* nested_cascade = 0;
int use_nested_cascade = 0;
const char* cascade_name =
    "./data/haarcascade_frontalface_alt.xml";//
const char* nested_cascade_name =
    "./data/haarcascade_eye_tree_eyeglasses.xml";

CvCapture* capture = 0;
IplImage *frame, *frame_copy = 0;
IplImage *image = 0;
const char* scale_opt = "--scale="; 
int scale_opt_len = (int)strlen(scale_opt);
const char* cascade_opt = "--cascade=";
int cascade_opt_len = (int)strlen(cascade_opt);
const char* nested_cascade_opt = "--nested-cascade";
int nested_cascade_opt_len = (int)strlen(nested_cascade_opt);
double scale = 1;
int num_components = 9;
double facethreshold = 9.0;

//opencv FaceRecogizer
cv::Ptr<cv::FaceRecognizer> model = cv::createEigenFaceRecognizer();
//cv::Ptr<cv::FaceRecognizer> model = cv::createFisherFaceRecognizer();
//cv::Ptr<cv::FaceRecognizer> model = cv::createLBPHFaceRecognizer();
vector<Mat> images;
vector<int> labels;

int main( int argc,char* argv[] )
{
    int judgement =0;
    if( argc == 1){
	cout<<"No picture"<<endl;
	return -1;
    }
    IplImage* img = cvLoadImage(argv[1],-1);
    if(img==NULL)
    {
	cout<<"couldn't load this pic :"<<argv[1]<<endl;
	return -1;
    }
    cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0); //加载分类器 
    if(!cascade) 
    {
        fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
		getchar();
        return -1;
    }
	model->set("threshold", 2100.0);
	string output_folder;
	output_folder = string("./einfacedata");

	//读取你的CSV文件路径
	string fn_csv = string("./einfacedata/at.txt");
	try
	{
		//通过./einfacedata/at.txt这个文件读取里面的训练图像和类别标签
		read_csv(fn_csv, images, labels);	
	}
	catch(cv::Exception &e)
	{
		cerr<<"Error opening file "<<fn_csv<<". Reason: "<<e.msg<<endl;
		exit(1);
	}

	//cout << images.size() << ":" << labels.size()<<endl;
	//如果没有读到足够的图片，就退出
	if(images.size() <= 2)
	{
		string error_message = "This demo needs at least 2 images to work.";
		CV_Error(CV_StsError, error_message);
	}


	/*static CvScalar colors[] =
   	 {
		{ { 128, 45, 0 } },
		{ { 0, 0, 255 } },
		{ { 0, 128, 255 } },
		{ { 0, 255, 255 } },
		{ { 0, 255, 0 } },
		{ { 255, 128, 0 } },
		{ { 255, 255, 0 } },
		{ { 255, 0, 255 } }
	 };*/
    IplImage *gray, *small_img;
    int i, j;
    storage = cvCreateMemStorage(0);
    gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
    small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
                         cvRound (img->height/scale)), 8, 1 );
    cvCvtColor( img, gray, CV_BGR2GRAY );  
    cvResize( gray, small_img, CV_INTER_LINEAR );
    cvEqualizeHist( small_img, small_img ); // Ö±·œÍŒŸùºâ»¯ 
    cvClearMemStorage( storage );

    if( cascade )
    {
        double t = (double)cvGetTickCount(); 
        CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
                                            1.1, 2, 0
                                            //|CV_HAAR_FIND_BIGGEST_OBJECT
                                            //|CV_HAAR_DO_ROUGH_SEARCH
                                            |CV_HAAR_DO_CANNY_PRUNING
                                            //|CV_HAAR_SCALE_IMAGE
                                            ,
                                            cvSize(30, 30) );
     //   t = (double)cvGetTickCount() - t; //
     //   printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
        for( i = 0; i < (faces ? faces->total : 0); i++ )
        {
            CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); 
            CvMat small_img_roi;
            CvSeq* nested_objects;
	    CvPoint center;
     //     CvScalar color = colors[i%8]; 
            int radius;
            center.x = cvRound((r->x + r->width*0.5)*scale); 
            center.y = cvRound((r->y + r->height*0.5)*scale);
            radius = cvRound(0.85*(r->width + r->height)*0.25*scale); 
			cvGetSubRect( small_img, &small_img_roi, *r );

			IplImage *result;
			CvRect roi;
			roi = *r;
			result = cvCreateImage( cvSize(r->width, r->height), img->depth, img->nChannels );
			cvSetImageROI(img,roi);

			cvCopy(img,result);
			cvResetImageROI(img);

			IplImage *resizeRes;
			CvSize dst_cvsize;
			dst_cvsize.width=(int)(100);
			dst_cvsize.height=(int)(100);
			resizeRes=cvCreateImage(dst_cvsize,result->depth,result->nChannels);

			cvResize(result,resizeRes,CV_INTER_NN);
			IplImage* img1 = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);
			cvCvtColor(resizeRes,img1,CV_BGR2GRAY);//cvCvtColor(src,des,CV_BGR2GRAY)

			//cvCircle( img, center, radius, color, 1, 8, 0 );
			//cvRectangle(img, pt1, pt2, color, 2);
			int predictedLabel = -1;

			Mat test = img1;
			//images[images.size() - 1] = test;
			model->train(images, labels);

			/*
			cvShowImage("resize", resizeRes);
			if (waitKey(10) == 48)
			{
				sprintf(llll, "../%d.jpg", nnn++);
				imwrite(llll,test);
			}*/
			//imwrite("../output.jpg",test);

			double predicted_confidence = 0.0;
			model->predict(test,predictedLabel,predicted_confidence);
			if(predictedLabel != -1)
			{	//cout<<"Yes"<<endl;
				judgement++;
//				break;
			}
			//else
			//	cout<<"No"<<endl;
			//cout << "predict:"<<model->predict(test) << endl;
			//cout << "predict:"<< predictedLabel << "\nconfidence:" << predicted_confidence << endl;  //Ê¶±ðÏûºÄÊ±Œä

            if( !nested_cascade )
                continue;

            nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage,
                                        1.1, 2, 0
                                        //|CV_HAAR_FIND_BIGGEST_OBJECT
                                        //|CV_HAAR_DO_ROUGH_SEARCH
                                        //|CV_HAAR_DO_CANNY_PRUNING
                                        //|CV_HAAR_SCALE_IMAGE
                                        ,
                                        cvSize(0, 0) );
            for( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ )
            {
                CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, j );
                center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
                center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
                radius = cvRound((nr->width + nr->height)*0.25*scale);
              //cvCircle( img, center, radius, color, 3, 8, 0 );
            }
        }
cout<<judgement<<"/"<<i<<endl;
	if(judgement > 0)
            cout<<"Yes"<<endl;
	else
	    cout<<"No"<<endl;
    }
//  cvShowImage( "cam", img );
    cvReleaseImage( &gray );
    cvReleaseImage( &small_img );
    return 0;
}




/*void cvText(IplImage* img, const char* text, int x, int y)  
{  
    CvFont font;  
    double hscale = 1.0;  
    double vscale = 1.0;  
    int linewidth = 2;  
    cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC,hscale,vscale,0,linewidth);  
	CvScalar textColor = cvScalar(175, 170, 85);
    CvPoint textPos =cvPoint(x, y);  
    cvPutText(img, text, textPos, &font,textColor);  
}*/



Mat norm_0_255(cv::InputArray _src)
{
	Mat src = _src.getMat();
	Mat dst;

	switch(src.channels())
	{
	case 1:
		cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC1);
		break;
	case 3:
		cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3);
		break;
	default:
		src.copyTo(dst);
		break;
	}

	return dst;
}


void read_csv(const string &filename, vector<Mat> &images, vector<int> &labels, char separator)
{
	std::ifstream file(filename.c_str(), ifstream::in);
	if(!file)
	{
		string error_message = "No valid input file was given.";
		CV_Error(CV_StsBadArg, error_message);
	}

	string line, path, classlabel;
	while(getline(file, line))
	{
		stringstream liness(line);
		getline(liness, path, separator);  
		getline(liness, classlabel);   
		if(!path.empty() && !classlabel.empty())
		{
			images.push_back(imread(path, 0));
			labels.push_back(atoi(classlabel.c_str()));
		}
	}
}